const spine = require('../lib/spine-webgl.js');

var lastFrameTime = Date.now() / 1000;
var canvas;
var shader;
var batcher;
var gl;
var mvp = new spine.webgl.Matrix4();
var assetManager;
var skeletonRenderer;
var debugRenderer;
var debugShader;
var shapes;
var skeletons = {};
var activeSkeleton = "yanhua";


const assetsPath = "https://duoduolu.top/spine/";

let currentCanvas;

function init(initCanvas, intGl) {
    // Setup canvas and WebGL context. We pass alpha: false to canvas.getContext() so we don't use premultiplied alpha when
    // loading textures. That is handled separately by PolygonBatcher.
    currentCanvas = canvas = initCanvas;
    gl = intGl;
    if (!gl) {
        console.error('WebGL is unavailable.');
        return;
    }
    const DPR = getApp().globalData.pixelRatio || 2
    canvas._width = canvas._width * DPR;
    canvas._height = canvas._height * DPR;
    // canvas._width = 750;
    // canvas._height = 1334;
    console.log(canvas._height, canvas._width)

    // Create a simple shader, mesh, model-view-projection matrix and SkeletonRenderer.
    shader = spine.webgl.Shader.newTwoColoredTextured(gl);
    batcher = new spine.webgl.PolygonBatcher(gl);
    mvp.ortho2d(canvas._width / -2, canvas._height / -2 + 100, canvas._width, canvas._height);
    skeletonRenderer = new spine.webgl.SkeletonRenderer(gl);
    shapes = new spine.webgl.ShapeRenderer(gl);
    assetManager = new spine.webgl.AssetManager(gl);

    // Tell AssetManager to load the resources for each model, including the exported .json file, the .atlas file and the .png
    // file for the atlas. We then wait until all resources are loaded in the load() method.
    wx._canvasContexts = {
        currentCanvas,
    };

    wx._canvasContexts[assetsPath + "01fu.png"] = {canvas: canvas, gl: gl,}
    assetManager.loadText(assetsPath + "01fu.json");
    assetManager.loadText(assetsPath + "01fu.atlas");
    assetManager.loadTexture(assetsPath + "01fu.png");

    wx._canvasContexts[assetsPath + "02niannianyouyu.png"] = {canvas: canvas, gl: gl,}
    assetManager.loadText(assetsPath + "02niannianyouyu.json");
    assetManager.loadText(assetsPath + "02niannianyouyu.atlas");
    assetManager.loadTexture(assetsPath + "02niannianyouyu.png");

    wx._canvasContexts[assetsPath + "yanhua.png"] = {canvas: canvas, gl: gl,}
    assetManager.loadText(assetsPath + "yanhua.json");
    assetManager.loadText(assetsPath + "yanhua.atlas");
    assetManager.loadTexture(assetsPath + "yanhua.png");

    wx._canvasContexts[assetsPath + "yanhua2.png"] = {canvas: canvas, gl: gl,}
    assetManager.loadText(assetsPath + "yanhua2.json");
    assetManager.loadText(assetsPath + "yanhua2.atlas");
    assetManager.loadTexture(assetsPath + "yanhua2.png");

    wx._canvasContexts[assetsPath + "yanhua3.png"] = {canvas: canvas, gl: gl,}
    assetManager.loadText(assetsPath + "yanhua3.json");
    assetManager.loadText(assetsPath + "yanhua3.atlas");
    assetManager.loadTexture(assetsPath + "yanhua3.png");

    currentCanvas.requestAnimationFrame(load);
}

function load() {
    // Wait until the AssetManager has loaded all resources, then load the skeletons.
    if (assetManager.isLoadingComplete()) {

        skeletons["yanhua"] = loadSkeleton("yanhua3", "animation", false);
        skeletons["yanhua2"] = loadSkeleton("yanhua2", "animation", false);
        skeletons["yanhua3"] = loadSkeleton("yanhua3", "animation", false);
        skeletons["fu"] = loadSkeleton("01fu", "animation", false);
        skeletons["niannianyouyu"] = loadSkeleton("02niannianyouyu", "animation", false);
        console.log('skeletons', skeletons)
        currentCanvas.requestAnimationFrame(render);
    } else {
        currentCanvas.requestAnimationFrame(load);
    }
}

var atlas;
var atlasLoader;
var animationStateData;

function loadSkeleton(name, initialAnimation, premultipliedAlpha, skin) {
    if (skin === undefined) skin = "default";
    // Load the texture atlas using name.atlas and name.png from the AssetManager.
    // The function passed to TextureAtlas is used to resolve relative paths.
    atlas = new spine.TextureAtlas(assetManager.get(assetsPath + name + ".atlas"), function(path) {
        return assetManager.get(assetsPath + path);
    });

    // Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
    atlasLoader = new spine.AtlasAttachmentLoader(atlas);

    // Create a SkeletonJson instance for parsing the .json file.
    var skeletonJson = new spine.SkeletonJson(atlasLoader);

    // Set the scale to apply during parsing, parse the file, and create a new skeleton.
    var skeletonData = skeletonJson.readSkeletonData(assetManager.get(assetsPath + name + ".json"));
    var skeleton = new spine.Skeleton(skeletonData);
    skeleton.setSkinByName(skin);
    var bounds = calculateBounds(skeleton);

    // Create an AnimationState, and set the initial animation in looping mode.
    animationStateData = new spine.AnimationStateData(skeleton.data);
    var animationState = new spine.AnimationState(animationStateData);
    animationState.setAnimation(0, initialAnimation, true);
    animationState.addListener({
        start: function(track) {
            console.log("Animation on track " + track.trackIndex + " started");
        },
        interrupt: function(track) {
            console.log("Animation on track " + track.trackIndex + " interrupted");
        },
        end: function(track) {
            console.log("Animation on track " + track.trackIndex + " ended");
        },
        disposed: function(track) {
            console.log("Animation on track " + track.trackIndex + " disposed");
        },
        complete: function(track) {
            console.log("Animation on track " + track.trackIndex + " completed");
        },
        event: function(track, event) {
            console.log("Event on track " + track.trackIndex + ": " + JSON.stringify(event));
        }
    })

    // Pack everything up and return to caller.
    return {
        skeleton: skeleton,
        state: animationState,
        bounds: bounds,
        premultipliedAlpha: premultipliedAlpha
    };
}

function calculateBounds(skeleton) {
    skeleton.setToSetupPose();
    skeleton.updateWorldTransform();
    var offset = new spine.Vector2();
    var size = new spine.Vector2();
    skeleton.getBounds(offset, size, []);
    return {
        offset: offset,
        size: size
    };
}

function render() {
    console.log('render')
    var now = Date.now() / 1000;
    var delta = now - lastFrameTime;
    lastFrameTime = now;

    // Update the MVP matrix to adjust for canvas size changes
    // resize();

    gl.clearColor(0, 0, 0, 0);

    gl.clear(gl.COLOR_BUFFER_BIT);

    // Apply the animation state based on the delta time.
    // var state = skeletons[activeSkeleton].state;
    // var skeleton = skeletons[activeSkeleton].skeleton;
    // var premultipliedAlpha = skeletons[activeSkeleton].premultipliedAlpha;
    // state.update(delta);
    // state.apply(skeleton);
    // skeleton.updateWorldTransform();

    // Bind the shader and set the texture and model-view-projection matrix.
    shader.bind();
    shader.setUniformi(spine.webgl.Shader.SAMPLER, 0);
    shader.setUniform4x4f(spine.webgl.Shader.MVP_MATRIX, mvp.values);

    // Start the batch and tell the SkeletonRenderer to render the active skeleton.
    batcher.begin(shader);
    // skeletonRenderer.premultipliedAlpha = premultipliedAlpha;
    for (const prop in skeletons) {
        const state = skeletons[prop].state;
        const skeleton = skeletons[prop].skeleton;
        state.update(delta);
        state.apply(skeleton);
        skeleton.updateWorldTransform();
        skeletonRenderer.draw(batcher, skeleton);
    }

    batcher.end();

    shader.unbind();

    currentCanvas.requestAnimationFrame(render);
}

function resize() {
    var bounds = skeletons[activeSkeleton].bounds;
    //
    console.log('bounds.size.x', bounds.size.x)
    console.log('bounds.size.y', bounds.size.y)
    var centerX = bounds.offset.x + bounds.size.x / canvas._DPR;
    var centerY = bounds.offset.y + bounds.size.y / canvas._DPR;
    var scaleX = bounds.size.x / canvas._width;
    var scaleY = bounds.size.y / canvas._height;
    var scale = Math.max(scaleX, scaleY) * 1.2;
    //if (scale < 1) scale = 1.2;
console.log('scale', scale)
    var width = canvas._width * scale;
    var height = canvas._height * scale;

    mvp.ortho2d(Math.floor(centerX - width / canvas._DPR), Math.floor(centerY - height / canvas._DPR), Math.floor(width), Math.floor(height));
    //mvp.ortho(centerX - width / 2, centerY - height / 2, width, height);
    gl.canvas.width = canvas._width;
    gl.canvas.height = canvas._height;
    console.log('canvas._width', canvas._width)
    console.log('canvas._height', canvas._height)
    gl.viewport(0, 0, canvas._width, canvas._height);
}

module.exports = {
    init
}
